﻿using KAsFrame.Application.Contracts;
using KAsFrame.Application.Contracts.User;
using KAsFrame.Common.Application;
using KAsFrame.Common.Dto;
using KAsFrame.Domain.School.Dto;
using KAsFrame.Domain.School.Entities;
using KAsFrame.Domain.User.Dto;
using KAsFrame.Domain.User.Entities;
using KAsFrame.DomainShared;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using KAsFrame.Common.Extensions;
using Microsoft.Extensions.Caching.Distributed;

namespace KAsFrame.Application.AppService.User
{
    // 无curd服务示例
    public class UserAppService : IUserAppService
    {
        private readonly IDistributedCache _cache;
        private readonly ISqlSugarClient _db;
        public UserAppService(IDistributedCache cache, ISqlSugarClient db)
        {
            _cache = cache;
            _db = db;
        }

        public async Task<LoginReturnDto> LoginAsync(LoginDto dto)
        {
            var userInfo = await _db.Queryable<UserInfo>().FirstAsync(x => x.Account == dto.Account);
            if (userInfo == null || userInfo.Password != $"{dto.Password}pwd{dto.Account}".Md5Encryption())
                throw new Exception("账户名不存在或密码错误");
            var token = Guid.NewGuid().ToString("N");
            await _cache.CacheAsync($"token:{token}", userInfo, 3600);
            var result = new LoginReturnDto()
            {
                Token = token,
                User = userInfo.SimpleMapTo<UserDto>()
            };
            return result;
        }

        public async Task<UserDto> RegisterAsync(RegisterDto dto)
        {
            var reg = new Regex(@"^[A-Za-z0-9]+$");
            if (!reg.IsMatch(dto.Account))
                throw new Exception("账户名必须由字母或数字构成");

            if (await _db.Queryable<UserInfo>().AnyAsync(x => x.Account == dto.Account))
                throw new Exception("账户名已存在");

            dto.Gender ??= (int)GenderEnums.Secrecy;
            dto.Password = $"{dto.Password}pwd{dto.Account}".Md5Encryption();

            var id = await _db.Insertable(dto.SimpleMapTo<UserInfo>()).ExcutedReturnIdAsync<UserInfo, long>();
            var entity = await _db.Queryable<UserInfo>().Where(x => x.Id.Equals(id)).SingleAsync();
            return entity.SimpleMapTo<UserDto>();
        }
    }
}
